package br.org.mestrado.vais.util;

import static java.lang.Math.PI;
import static java.lang.Math.atan;
import static java.lang.Math.cos;
import static java.lang.Math.exp;
import static java.lang.Math.pow;
import static java.lang.Math.random;
import static java.lang.Math.sin;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.atomic.AtomicInteger;

import br.org.mestrado.vais.Anticorpo;

public enum PROBLEMA {

	DTLZ1 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double gt = 0;
			for (i = n - k + 1; i <= n; i++) {

				final double g1 = pow(
						anticorpo.getDecisionVariables()[i - 1] - 0.5d, 2);

				final double g2 = cos(20 * PI
						* (anticorpo.getDecisionVariables()[i - 1] - 0.5d));

				gt += g1 - g2;
			}

			double g = 100 * (anticorpo.getDecisionVariables().length + gt);

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {

				double f = 0.5 * (1 + g);

				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {

					f *= anticorpo.getDecisionVariables()[j - 1];
				}

				if (i > 1) {

					f *= (1 - anticorpo.getDecisionVariables()[(anticorpo
							.getObjectives().length
							- i + 1) - 1]);
				}

				anticorpo.getObjectives()[i - 1] = new BigDecimal(f,
						MATH_CONTEXT).doubleValue();
			}

			if (!isStart)
				fitnessCout.incrementAndGet();
		}
	},
	DTLZ2 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;

			int j = 0;

			int n = anticorpo.getDecisionVariables().length;

			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1] - 0.5, 2);
			}

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {
				double f = (1 + g);
				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= Math.cos(anticorpo.getDecisionVariables()[j - 1]
							* Math.PI / 2);
				}
				if (i > 1) {
					f *= Math.sin(anticorpo.getDecisionVariables()[(anticorpo
							.getObjectives().length
							- i + 1) - 1]
							* Math.PI / 2);
				}

				final BigDecimal bigDecimalfx = new BigDecimal(f, MATH_CONTEXT);

				anticorpo.getObjectives()[i - 1] = bigDecimalfx.doubleValue();
			}

			if (!isStart)
				fitnessCout.incrementAndGet();

		}
		/*
		 * @Override public ArrayList<SolucaoNumerica> obterFronteira(int nVars,
		 * int nObjs, int numSol) { ArrayList<SolucaoNumerica> melhores = new
		 * ArrayList<SolucaoNumerica>();
		 * 
		 * Random rand = new Random(); rand.setSeed(1000);
		 * 
		 * while (melhores.size() < numSol) {
		 * 
		 * SolucaoNumerica melhor = new SolucaoNumerica(nVars, nObjs);
		 * 
		 * for (int i = nObjs - 1; i < nVars; i++) { melhor.setVariavel(i, 0.5);
		 * }
		 * 
		 * for (int i = 0; i < nObjs - 1; i++) { double newVal =
		 * rand.nextDouble(); melhor.setVariavel(i, newVal); }
		 * 
		 * double somaParcial = 0;
		 * 
		 * final Anticorpo anticorpo = new Anticorpo(0, nObjs, nVars, numSol, 0,
		 * 0, this, null, 0);
		 * 
		 * System.arraycopy(melhor.getVariaveis(), 0, anticorpo
		 * .getDecisionVariables(), 0, nVars);
		 * 
		 * eval(anticorpo, true);
		 * 
		 * System.arraycopy(anticorpo.getObjectives(), 0, melhor.objetivos, 0,
		 * nObjs);
		 * 
		 * // calcularObjetivos(melhor);
		 * 
		 * for (int i = 0; i < melhor.m; i++) { somaParcial +=
		 * melhor.objetivos[i] * melhor.objetivos[i]; } if (somaParcial == 1) {
		 * melhores.add(melhor); } }
		 * 
		 * return melhores; }
		 */
	},
	DTLZ3 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			for (i = n - k + 1; i <= n; i++) {

				final double g1 = pow(
						anticorpo.getDecisionVariables()[i - 1] - 0.5, 2);

				final double g2 = cos(20 * PI
						* (anticorpo.getDecisionVariables()[i - 1] - 0.5));

				g += g1 - g2;
			}
			g = 100 * (anticorpo.getObjectives().length + g);

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {

				double f = (1 + g);

				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= cos(anticorpo.getDecisionVariables()[j - 1] * (PI / 2));
				}

				if (i > 1) {
					f *= sin(anticorpo.getDecisionVariables()[(anticorpo
							.getObjectives().length
							- i + 1) - 1]
							* (PI / 2));
				}

				anticorpo.getObjectives()[i - 1] = new BigDecimal(f,
						MATH_CONTEXT).doubleValue();

			}

			if (!isStart)
				fitnessCout.incrementAndGet();
		}
	},
	DTLZ4 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			int i = 0;
			int j = 0;
			double alpha = 100;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1] - 0.5, 2);
			}

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {
				double f = (1 + g);
				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {
					f *= Math.cos(Math.pow(
							anticorpo.getDecisionVariables()[j - 1], alpha)
							* Math.PI / 2);
				}
				if (i > 1) {
					f *= Math.sin(Math.pow(
							anticorpo.getDecisionVariables()[(anticorpo
									.getObjectives().length
									- i + 1) - 1], alpha)
							* Math.PI / 2);
				}

				final BigDecimal bigDecimalfx = new BigDecimal(f, MATH_CONTEXT);

				anticorpo.getObjectives()[i - 1] = bigDecimalfx.doubleValue();
			}
			if (!isStart)
				fitnessCout.incrementAndGet();

		}
		/*
		 * @Override public ArrayList<SolucaoNumerica> obterFronteira(int nVars,
		 * int nObjs, int numSol) { ArrayList<SolucaoNumerica> melhores = new
		 * ArrayList<SolucaoNumerica>();
		 * 
		 * Random rand = new Random(); rand.setSeed(1000);
		 * 
		 * while (melhores.size() < numSol) { SolucaoNumerica melhor = new
		 * SolucaoNumerica(nVars, nObjs);
		 * 
		 * for (int i = nObjs - 1; i < nVars; i++) { melhor.setVariavel(i, 0.5);
		 * }
		 * 
		 * for (int i = 0; i < nObjs - 1; i++) { double newVal =
		 * rand.nextDouble(); melhor.setVariavel(i, newVal); }
		 * 
		 * final Anticorpo anticorpo = new Anticorpo(0, nObjs, nVars, numSol, 0,
		 * 0, this, null, 0);
		 * 
		 * System.arraycopy(melhor.getVariaveis(), 0, anticorpo
		 * .getDecisionVariables(), 0, nVars);
		 * 
		 * eval(anticorpo, true);
		 * 
		 * System.arraycopy(anticorpo.getObjectives(), 0, melhor.objetivos, 0,
		 * nObjs);
		 * 
		 * melhores.add(melhor);
		 * 
		 * }
		 * 
		 * return melhores; }
		 */
	},
	DTLZ5 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double[] theta = new double[anticorpo.getObjectives().length];

			double t = 0;

			double g = 0;

			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1] - 0.5, 2);
			}

			t = Math.PI / (4 * (1 + g));

			theta[0] = (anticorpo.getDecisionVariables()[0] * Math.PI) / 2;

			for (i = 2; i <= anticorpo.getObjectives().length - 1; i++) {
				theta[i - 1] = t
						* (1 + 2 * g * anticorpo.getDecisionVariables()[i - 1]);
			}

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {

				double f = (1 + g);

				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {

					f *= Math.cos(theta[j - 1]);

				}

				if (i > 1) {

					f *= Math
							.sin(theta[(anticorpo.getObjectives().length - i + 1) - 1]);
				}

				anticorpo.getObjectives()[i - 1] = new BigDecimal(f,
						MATH_CONTEXT).doubleValue();
			}

			if (!isStart)
				fitnessCout.incrementAndGet();

		}
	},
	DTLZ6 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double[] theta = new double[anticorpo.getObjectives().length];

			double t = 0;

			double g = 0;

			for (i = n - k + 1; i <= n; i++) {
				g += Math.pow(anticorpo.getDecisionVariables()[i - 1], 0.1);
			}

			t = Math.PI / (4 * (1 + g));

			theta[0] = anticorpo.getDecisionVariables()[0] * Math.PI / 2;

			for (i = 2; i <= anticorpo.getObjectives().length - 1; i++) {
				theta[i - 1] = t
						* (1 + 2 * g * anticorpo.getDecisionVariables()[i - 1]);
			}

			for (i = 1; i <= anticorpo.getObjectives().length; i++) {

				double f = (1 + g);

				for (j = anticorpo.getObjectives().length - i; j >= 1; j--) {

					f *= Math.cos(theta[j - 1]);
				}

				if (i > 1) {

					f *= Math
							.sin(theta[(anticorpo.getObjectives().length - i + 1) - 1]);
				}

				anticorpo.getObjectives()[i - 1] = new BigDecimal(f,
						MATH_CONTEXT).doubleValue();
			}

			if (!isStart)
				fitnessCout.incrementAndGet();
		}
	},
	DTLZ7 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			int i = 0;
			int j = 0;
			int n = anticorpo.getDecisionVariables().length;
			int k = n - anticorpo.getObjectives().length + 1;

			double g = 0;
			double h = 0;

			for (i = n - k + 1; i <= n; i++) {
				g += anticorpo.getDecisionVariables()[i - 1];
			}
			g = 1 + 9 * g / k;

			for (i = 1; i <= anticorpo.getObjectives().length - 1; i++) {
				anticorpo.getObjectives()[i - 1] = anticorpo
						.getDecisionVariables()[i - 1];
			}

			for (j = 1; j <= anticorpo.getObjectives().length - 1; j++) {
				h += anticorpo.getDecisionVariables()[j - 1]
						/ (1 + g)
						* (1 + Math.sin(3 * Math.PI
								* anticorpo.getDecisionVariables()[j - 1]));
			}

			h = anticorpo.getObjectives().length - h;

			anticorpo.getObjectives()[anticorpo.getObjectives().length - 1] = (1 + g)
					* h;

			if (!isStart)
				fitnessCout.incrementAndGet();
		}
	},
	DTLZ8 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

		}
	},
	DTLZ9 {
		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

		}
	},
	TANAKA {

		@Override
		public void eval(final Anticorpo anticorpo, boolean isStart) {

			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui duas variaveis de decisão
			assert anticorpo.getDecisionVariables().length == 2;

			anticorpo.getObjectives()[0] = new BigDecimal(anticorpo
					.getDecisionVariables()[0], MATH_CONTEXT).doubleValue();

			anticorpo.getObjectives()[1] = new BigDecimal(anticorpo
					.getDecisionVariables()[1], MATH_CONTEXT).doubleValue();

			if (!isStart)
				fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(double... objectives) {

			for (double d : objectives) {

				if (d < 0.0d || d > Math.PI) {
					return false;
				}
			}

			return true;
		}

		@Override
		public boolean isConstrained(double... variaveis) {

			final double var_l1 = variaveis[0];

			final double var_l2 = variaveis[1];

			// verifica retrição 1
			double c_1_l = 0.1 * cos(16 * atan(var_l1 / var_l2));

			double c_1_ll = pow(var_l1, 2) + pow(var_l2, 2);

			double c_1 = c_1_ll - 1 - c_1_l;

			// verifica restrição 2
			double c_2 = new BigDecimal(pow(var_l1 - 0.5, 2)
					+ pow(var_l2 - 0.5, 2), MATH_CONTEXT).doubleValue();

			if (c_1 < 0.0d || c_2 > 0.5d)
				return false;

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = new BigDecimal(random() * PI, MATH_CONTEXT)
					.doubleValue();

		}
	},
	DEB1999 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			// normaliza primeiro
			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui duas variaveis de decisão
			assert anticorpo.getDecisionVariables().length == 2;

			double f = anticorpo.getDecisionVariables()[0];

			anticorpo.getObjectives()[0] = new BigDecimal(f, MATH_CONTEXT)
					.doubleValue();

			double g1 = new BigDecimal(anticorpo.getDecisionVariables()[1],
					MATH_CONTEXT).doubleValue();

			double gl1 = new BigDecimal(Math.exp(-Math.pow(
					(g1 - 0.2d) / 0.004d, 2)), MATH_CONTEXT).doubleValue();

			double gl2 = new BigDecimal(Math.exp(-Math.pow((g1 - 0.6d) / 0.4d,
					2)), MATH_CONTEXT).doubleValue();

			double g = new BigDecimal(2 - gl1 - (0.8 * gl2), MATH_CONTEXT)
					.doubleValue();

			f = g / anticorpo.getDecisionVariables()[0];

			anticorpo.getObjectives()[1] = new BigDecimal(f, MATH_CONTEXT)
					.doubleValue();

			if (!isStart)
				fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(double... objectives) {

			for (double d : objectives) {
				// teclado não tem pipe
				if (d < 0.1d || d > 1d) {
					return false;
				}

			}

			return true;
		}
	},
	ZITZILER {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			double var_l = anticorpo.getDecisionVariables()[0];

			// calcula próximo objetivo
			double f1 = 1 - exp(-4 * var_l) * pow(sin(6 * PI * var_l), 6);

			anticorpo.getObjectives()[0] = new BigDecimal(f1, MATH_CONTEXT)
					.doubleValue();

			// cálcula próximo objetivo
			double g = 0;

			double w_t = -var_l;

			for (double d : anticorpo.getDecisionVariables()) {
				w_t += d;
			}

			// w_t -= var_l;

			g = 1 + (9 * pow(w_t
					/ (anticorpo.getDecisionVariables().length - 1), 0.25d));

			double h = 1 - pow(f1 / g, 2);

			double f2 = g * h;

			anticorpo.getObjectives()[1] = new BigDecimal(f2, MATH_CONTEXT)
					.doubleValue();

			if (!isStart)
				fitnessCout.incrementAndGet();

		}
	},
	OSYCZKA1995 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {
			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui seis variaveis objetivos
			assert anticorpo.getDecisionVariables().length == 6;

			// formatação de valores intermediários
			double gl1 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[0] - 2, 2), MATH_CONTEXT)
					.doubleValue();

			double gl2 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[1] - 2, 2), MATH_CONTEXT)
					.doubleValue();

			double gl3 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[2] - 1, 2), MATH_CONTEXT)
					.doubleValue();

			double gl4 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[3] - 4, 2), MATH_CONTEXT)
					.doubleValue();

			double gl5 = new BigDecimal(Math.pow(anticorpo
					.getDecisionVariables()[4] - 1, 2), MATH_CONTEXT)
					.doubleValue();

			// f1
			double f1 = -((25 * gl1) + gl2 + gl3 + gl4 + gl5);

			// f2
			double f2 = 0d;

			for (double var : anticorpo.getDecisionVariables()) {
				f2 += new BigDecimal(Math.pow(var, 2), MATH_CONTEXT)
						.doubleValue();
			}

			anticorpo.getObjectives()[0] = new BigDecimal(f1, MATH_CONTEXT)
					.doubleValue();

			anticorpo.getObjectives()[1] = new BigDecimal(f2, MATH_CONTEXT)
					.doubleValue();

			if (!isStart)
				fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(double... objectives) {

			for (int pointer = 0; pointer < objectives.length; pointer++) {

				if ((pointer == 0 || pointer == 1 || pointer == 5)
						&& (objectives[pointer] < 0 || objectives[pointer] > 10))
					return false;
				else if ((pointer == 2 || pointer == 4)
						&& (objectives[pointer] < 1 || objectives[pointer] > 5))
					return false;
				else if (pointer == 3
						&& (objectives[pointer] < 0 || objectives[pointer] > 6))
					return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(double... variaveis) {

			// valida restrição 1
			double c1 = new BigDecimal(variaveis[0] + variaveis[1] - 2,
					MATH_CONTEXT).doubleValue();

			// valida restrição 2
			double c2 = new BigDecimal(6 - variaveis[0] - variaveis[1],
					MATH_CONTEXT).doubleValue();

			// valida restrição 3
			double c3 = new BigDecimal(2 + variaveis[0] - variaveis[1],
					MATH_CONTEXT).doubleValue();

			// valida restrição 4
			double c4 = new BigDecimal(2 - variaveis[0] + (3 * variaveis[1]),
					MATH_CONTEXT).doubleValue();

			// valide restrição 5
			double c5 = new BigDecimal(4 - pow(variaveis[2] - 3, 2)
					- variaveis[3], MATH_CONTEXT).doubleValue();

			// valida restrição 6
			double c6 = new BigDecimal(Math.pow(variaveis[4] - 3, 2)
					+ variaveis[5] - 4, MATH_CONTEXT).doubleValue();

			if (c1 < 0 || c2 < 0 || c3 < 0 || c4 < 0 || c5 < 0 || c6 < 0)
				return false;

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			// não tem pipe
			if (pointer == 0 || pointer == 1 || pointer == 5)
				vars[pointer] = new BigDecimal(Math.random() * 10, MATH_CONTEXT)
						.doubleValue();
			if (pointer == 2 || pointer == 4)
				vars[pointer] = new BigDecimal(Math.random() * 5, MATH_CONTEXT)
						.doubleValue();
			if (pointer == 3)
				vars[pointer] = new BigDecimal(Math.random() * 6, MATH_CONTEXT)
						.doubleValue();
		}

	},

	KITA1996 {

		@Override
		public void eval(final Anticorpo anticorpo, boolean isStart) {
			// testa se possui duas variaveis objetivos
			assert anticorpo.getObjectives().length == 2;

			// testa se possui seis variaveis objetivos
			assert anticorpo.getDecisionVariables().length == 2;

			double var1 = anticorpo.getDecisionVariables()[0];

			double var2 = anticorpo.getDecisionVariables()[1];

			double f1 = (Math.pow(var1, 2) * -1) + var2;

			double f2 = (0.5D * var1) + var2 + 1;

			anticorpo.getObjectives()[0] = f1;

			anticorpo.getObjectives()[1] = f2;

			if (!isStart)
				fitnessCout.incrementAndGet();

		}

		@Override
		public boolean insideDomain(double... objectives) {

			for (double d : objectives) {

				if (d < 0d || d > 7d)

					return false;
			}

			return true;
		}

		@Override
		public boolean isConstrained(double... variaveis) {

			double var1 = variaveis[0];

			double var2 = variaveis[1];

			double c1 = ((1 / 6) * var1) + var2 - (13 / 2);

			double c2 = ((1 / 2) * var1) + var2 - (15 / 2);

			double c3 = (5 * var1) + var2 - 30;

			if (c1 > 0 || c2 > 0 || c3 > 0)
				return false;

			return true;
		}

		@Override
		public void startDecisionVar(double[] vars, int pointer) {

			vars[pointer] = Math.random() * 7d;

		}

	},
	VIENNET1995 {

		@Override
		public void eval(Anticorpo anticorpo, boolean isStart) {

		}

	}

	;

	public abstract void eval(final Anticorpo anticorpo, boolean isStart);

	public int[] chooseVariables(final int variables_size,
			final int totalVariablesToMutate) {

		final int[] vars = new int[totalVariablesToMutate];

		if (totalVariablesToMutate > 0) {

			Arrays.fill(vars, -1);

			final Random random = new Random();

			Set<Integer> integers = new HashSet<Integer>();

			for (int pointer = 0; pointer < vars.length; pointer++) {

				final int r = random.nextInt(variables_size);

				if (!integers.contains(r)) {

					integers.add(r);

					vars[pointer] = r;
				} else
					pointer--;
			}
		}

		Arrays.sort(vars);

		return vars;

	}

	double[] preCalcnormalize(final double upperBound, final double lowerBound,
			final double... variaveis) {

		final double[] vars = new double[variaveis.length];

		final double numerador = upperBound - lowerBound;

		for (int pointer = 0; pointer < vars.length; pointer++) {
			vars[pointer] = (variaveis[pointer] - lowerBound) / numerador;
		}

		return vars;
	}

	public boolean insideDomain(double... objectives) {

		for (double d : objectives) {

			if (d < 0d || d > 1d) {
				return false;
			}
		}

		return true;
	}

	public boolean isConstrained(double... variaveis) {
		return true;
	}

	public void startDecisionVar(double[] vars, int pointer) {

		final BigDecimal bigDecimal = new BigDecimal(Math.random(),
				MATH_CONTEXT);

		vars[pointer] = bigDecimal.doubleValue();
	}

	static private AtomicInteger fitnessCout = new AtomicInteger();

	private int maxFitnessTotal = 0;

	// precisão do cálculo
	public static final MathContext MATH_CONTEXT = new MathContext(Double.SIZE,
			RoundingMode.HALF_EVEN);

	public boolean stopNow() {

		return fitnessCout.get() >= maxFitnessTotal;

	}

	public void setMaxFitnessCount(final int max) {
		maxFitnessTotal = max;

	}

	public int getFitnessValue() {

		return fitnessCout.get();
	}

	public void resetFitnessValue() {
		fitnessCout.set(0);
	}

}
